Skip to main content

Switch Thinking: The Case for Traditional for Loops

Iteration is a fundamental concept in programming, and modern languages provide a variety of tools to simplify it. Constructs like range in Go, or forEach in JavaScript, abstract away much of the complexity of traversing collections. While these tools are convenient, they often limit the way we think about iteration, locking us into predictable patterns that don’t always suit our needs.

This article explores the benefits of revisiting traditional for loops, particularly in Go, and how they provide unmatched flexibility for solving complex problems. By embracing the explicit structure of for loops, we can break free from constraints and rediscover iteration as a creative process.

My current language of focus is Go, so all my examples here (and in many other places in this section will be written in Go, but of course these principles are language agnostic). See this article for a cross language iteration comparison.


Why Traditional for Loops Matter

The traditional for loop in Go:

for init; condition; post {
// loop body
}

provides three key components:

  1. Initialization: Declare and initialize loop variables.
  2. Condition: Define when the loop should terminate.
  3. Post-operation: Modify variables after each iteration.

This structure gives you granular control over iteration. Unlike range, which enforces sequential traversal, traditional for loops let you define:

  • Custom start and end points.
  • Non-linear traversal patterns.
  • Dynamic behavior based on runtime conditions.

Go and the Absence of while

Go doesn’t have a while loop. Instead, the for loop can mimic while by omitting the initialization and post-operation steps:

for condition {
// loop body
}

This reinforces the versatility of Go’s for loop as a one-stop solution for all iteration needs.


Breaking Free from range

While range simplifies common tasks, it imposes a linear progression. This abstraction is often limiting when you need to:

  • Traverse a collection in custom patterns (maybe as part of a matrix)
  • Skip or repeat elements dynamically.
  • Terminate the loop when an external condition is met, such as finding a specific value or responding to a signal from outside the loop. This is possible in both range and traditional for loops using break, but traditional for loops can offer additional flexibility in handling indices or conditions dynamically.

Example: Skipping Dynamically Without break

Suppose you want to iterate through a slice but skip a variable number of elements dynamically based on some logic. With range, this isn't directly possible because the loop variable is read-only and cannot be modified mid-iteration.

Traditional for Loop Solution
nums := []int{1, 2, 3, 4, 5, 6, 7, 8}
skip := 2

for i := 0; i < len(nums); {
fmt.Println(nums[i]) // Process the element
if nums[i] % 2 == 0 {
i += skip // Dynamically skip based on logic
} else {
i++ // Normal increment
}
}

Advanced Iteration Patterns

Traditional for loops excel when dealing with 2D structures like matrices. Let’s explore some creative patterns:

1. Diagonal Traversal

matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}

//Todo add updated code

2. Spiral Traversal

matrix := [][]int{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
}

top, left := 0, 0
bottom, right := len(matrix)-1, len(matrix[0])-1

for top <= bottom && left <= right {
// Top row
for i := left; i <= right; i++ {
fmt.Println(matrix[top][i])
}
top++

// Right column
for i := top; i <= bottom; i++ {
fmt.Println(matrix[i][right])
}
right--

if top <= bottom {
// Bottom row
for i := right; i >= left; i-- {
fmt.Println(matrix[bottom][i])
}
bottom--
}

if left <= right {
// Left column
for i := bottom; i >= top; i-- {
fmt.Println(matrix[i][left])
}
left++
}
}

3. Middle-Out Traversal

Start from the center of a matrix and move outward in concentric layers. This requires calculating boundaries dynamically based on the center index.


When to Use Traditional for Loops

Traditional for loops are ideal when:

  • You need explicit control over the iteration process.
  • The traversal pattern is non-linear or dynamic.
  • Indices play a critical role in your logic.
  • You’re working with multi-dimensional structures.

Conclusion

The traditional for loop is more than a relic of the past. It’s a powerful tool that provides unmatched flexibility for solving complex problems. By stepping away from built-in abstractions like range, you can unlock new ways to think about iteration—whether you’re working with slices, matrices, or custom data structures.

This is just the beginning. In upcoming articles, we’ll explore specific iteration patterns like zigzag, spirals, and center-out traversals in more detail. Stay tuned for a deep dive into the world of creative iteration—powered by the humble for loop.